package com.xiaomaoguai.javassist.kepler.config;

import com.alibaba.fastjson.JSON;
import com.xiaomaoguai.fcp.pre.kepler.convert.core.ConvertTemplate;
import com.xiaomaoguai.fcp.pre.kepler.convert.utils.ToStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @author WeiHui
 * @version v1.0.0
 * @date 2019/4/20 14:12
 * @since JDK 1.8
 */
public class HandlerConvertClientInvocation implements InvocationHandler {

	private Class<?> serviceInterface;

	private ConvertTemplate convertTemplate;

	public HandlerConvertClientInvocation(Class<?> serviceInterface, ConvertTemplate convertTemplate) {
		this.serviceInterface = serviceInterface;
		this.convertTemplate = convertTemplate;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) {
		if (ToStringUtils.TO_STRING.equals(method.getName())) {
			return ToStringUtils.handlerToString(this, method, args);
		}
		String simpleName = serviceInterface.getSimpleName();
		String handlerName = StringUtils.uncapitalize(StringUtils.removeEnd(simpleName, HandlerClientAutoGenerator.CONVERT_CLIENT_SUFFIX));

		ImmutablePair<String, Object> immutablePair = resolve(method, args);
		String productCode = immutablePair.getLeft();
		Object param = immutablePair.getRight();

		String inputNodeName = NodeSupport.IN.generateHandlerConvertNodeName(productCode, null, handlerName, null);
		return convertTemplate.buildDataByNodeName(inputNodeName, param, method.getReturnType());
	}

	/**
	 * 解析
	 *
	 * @param method
	 * @param args
	 * @return
	 */
	private ImmutablePair<String, Object> resolve(Method method, Object[] args) {
		String methodName = method.getName();
		int length = args.length;
		String productCode = null;
		Object root = null;
		Object arg = args[0];
		Class<?> clazz = arg.getClass();
		switch (methodName) {
			case "convert":
				if (length == 1) {
					if (Map.class.isAssignableFrom(clazz)) {
						Map<Object, Object> objectMap = (Map<Object, Object>) args[0];
						productCode = (String) objectMap.get("productCode");
					} else {
						productCode = JSON.parseObject(JSON.toJSONString(arg)).getString("productCode");
					}
					root = arg;
				} else {
					productCode = (String) arg;
					root = args[1];
				}
				break;
		}
		return new ImmutablePair<>(productCode, root);
	}

}